package com.echo.im.client.config;

import com.echo.im.client.config.condition.UserStatusServiceEnabledCondition;
import com.echo.im.client.constant.RedisConstant;
import com.echo.im.client.status.UserStatusRepository;
import com.echo.im.client.status.UserStatusService;
import com.echo.im.client.status.UserStatusServiceImpl;
import com.echo.im.client.status.cache.CacheService;
import com.echo.im.client.status.cache.CacheServiceImpl;
import com.echo.im.client.status.data.DataService;
import com.echo.im.client.status.data.RedisDataServiceImpl;
import com.echo.im.client.status.listener.UserStatusListener;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.CacheManager;
import org.springframework.cache.caffeine.CaffeineCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Conditional;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.data.redis.listener.adapter.MessageListenerAdapter;

import java.time.Duration;

/**
 * @author echo
 */
@Configuration(proxyBeanMethods = false)
@Conditional(UserStatusServiceEnabledCondition.class)
public class UserStatusConfig {

    @Bean
    public UserStatusListener userStatusListener(CacheService cacheService){
        return new UserStatusListener(cacheService);
    }

    @Bean
    public UserStatusService userStatusService(CacheService cacheService,
                                               RedisTemplate<String,Object> redisTemplate){
        DataService dataService = new RedisDataServiceImpl(redisTemplate);
        UserStatusRepository userStatusRepository = new UserStatusRepository(cacheService, dataService);
        return new UserStatusServiceImpl(userStatusRepository);
    }

    @Bean
    public CacheService cacheService(@Qualifier("caffeineCacheManager") CacheManager cacheManager){
        return new CacheServiceImpl(cacheManager);
    }

    @Bean
    public RedisMessageListenerContainer container(RedisConnectionFactory connectionFactory,
                                                   MessageListenerAdapter listenerAdapter) {
        RedisMessageListenerContainer container = new RedisMessageListenerContainer();
        container.setConnectionFactory(connectionFactory);
        container.addMessageListener(listenerAdapter, new PatternTopic(RedisConstant.IM_USER_STATUS_CHANNEL));
        return container;
    }

    @Bean
    public MessageListenerAdapter listenerAdapter(UserStatusListener listener) {
        return new MessageListenerAdapter(listener, "onMessage");
    }

    @Bean("caffeineCacheManager")
    public CacheManager caffeineCacheManager() {
        CaffeineCacheManager cacheManager = new CaffeineCacheManager();
        cacheManager.setCaffeine(
                com.github.benmanes.caffeine.cache.Caffeine.newBuilder()
                        .maximumSize(100000)
                        .expireAfterWrite(Duration.ofMinutes(10))
        );
        return cacheManager;
    }
}
